<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Vueテストハンドブック</title>
    <meta name="description" content="">
    <link rel="icon" href="https://lmiller1990.github.io/vue-testing-handbook/img/favicon.png">
  <meta property="og:title" content="Vue Testing Handbook">
  <meta property="og:description" content="Vue testing handbook">
  <meta property="og:type" content="website">
  <meta property="og:url" content="https://lmiller1990.github.io/vue-testing-handbook/">
  <meta property="og:image" content="https://lmiller1990.github.io/vue-testing-handbook/img/og.png">
    
    <link rel="preload" href="/vue-testing-handbook/assets/css/0.styles.99f2ca3b.css" as="style"><link rel="preload" href="/vue-testing-handbook/assets/js/app.14051834.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/3.119a321e.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/2.94957ecd.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/25.48371e8a.js" as="script"><link rel="prefetch" href="/vue-testing-handbook/assets/js/10.7b1750c8.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/100.87c02eb0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/101.9f86f8af.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/102.7cf5b3b5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/103.9a447cc0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/104.d960f455.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/105.42aa8c19.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/106.fa067e24.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/107.f6145328.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/108.4251a9d9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/109.6e04b4aa.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/11.c9a15d65.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/110.203be49f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/111.e66d4c1a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/112.d5cf2637.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/113.0e1df8ea.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/114.b1d0a5f5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/115.d21ab6a2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/116.e13d34ff.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/117.532bedf9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/118.b99c8d4d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/119.97666be8.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/12.8ec4d737.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/120.e5fbc47b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/121.2d6cedde.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/122.7dc3c3fc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/123.82fcb804.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/124.affd46d3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/125.10d1ddcb.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/126.8ca1978a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/127.7b76e158.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/128.e0d8fdce.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/129.e861e49f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/13.96ee585a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/130.474092c4.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/131.71e4509c.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/132.b48fe96d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/133.9268758a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/134.6a042ef6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/135.6df261f9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/136.8aab4165.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/137.60d15690.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/138.29f827fd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/139.e8db710e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/14.522b77b9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/140.8a3b2b26.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/141.cd5f96df.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/142.04a47072.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/143.ac0cb5e1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/144.c69a73ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/15.2f00de2d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/16.d120a376.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/17.9260e267.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/18.4e3a9d5e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/19.bfe7cfa3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/20.52828530.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/21.4d92035b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/22.49a88bda.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/23.79de1f16.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/24.f45f108e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/26.bc7a5470.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/27.49bfeced.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/28.b697055e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/29.0ef469da.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/30.bd209efe.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/31.ddf8aa10.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/32.95ec3267.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/33.52cf0ebc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/34.73b1ca03.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/35.be79f171.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/36.52a4dcd2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/37.a02e83c0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/38.2a809ae1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/39.31de0194.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/4.a86536d1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/40.4a3cfcb7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/41.db485265.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/42.8c4375ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/43.2f241bb5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/44.43539973.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/45.619b76a6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/46.00e17cc1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/47.faf51fac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/48.840de9e5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/49.3410da74.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/5.d3ebdf21.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/50.647913c0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/51.4990b428.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/52.85ff4209.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/53.7bbf915a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/54.1fc8316d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/55.374436d3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/56.40ebbbe6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/57.40d9cc46.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/58.37ab0bcf.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/59.8df2efac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/6.637082cf.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/60.326b4bdd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/61.449fcfe0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/62.f05ac3d6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/63.e1723f7e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/64.5b9e17ef.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/65.52e8ce24.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/66.cbdf653b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/67.522e5bfd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/68.1c27735b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/69.1f5624e9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/7.43089f9d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/70.49fd6b50.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/71.20acc429.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/72.715f4620.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/73.ac123d7d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/74.59a869d0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/75.772485ad.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/76.b887e73a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/77.70e54ee3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/78.2306c3e7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/79.e01a6cd1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/8.4c4cdaa7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/80.c12fc82f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/81.44ef90b7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/82.ff3143a2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/83.22084435.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/84.485c66f4.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/85.d8afef97.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/86.2ba55e96.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/87.d5642266.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/88.3ad1f8ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/89.e370d2fc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/9.a0f31be6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/90.2c039dfb.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/91.2c1dd586.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/92.571cd8ae.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/93.b88ae6f6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/94.16000348.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/95.79a96428.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/96.c86f8cad.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/97.bc1d6c91.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/98.34c6a547.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/99.e1174558.js">
    <link rel="stylesheet" href="/vue-testing-handbook/assets/css/0.styles.99f2ca3b.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/vue-testing-handbook/ja/" class="home-link router-link-active"><!----> <span class="site-name">Vueテストハンドブック</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Select language" class="dropdown-title"><span class="title">言語</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/vuex-actions.html" class="nav-link">English</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/vuex-actions.html" class="nav-link">v3</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ja/vuex-actions.html" class="nav-link router-link-exact-active router-link-active">日本語</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ru/vuex-actions.html" class="nav-link">Русский (Vue.js 2)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/ru/vuex-actions.html" class="nav-link">Русский (Vue.js 3)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/zh-CN/vuex-actions.html" class="nav-link">简体中文</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ko/vuex-actions.html" class="nav-link">한국어</a></li></ul></div></div> <a href="https://github.com/lmiller1990/vue-testing-handbook" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><a href="https://vuejs-course.com/" target="_blank"><img id="ad" src="https://raw.githubusercontent.com/lmiller1990/vue-testing-handbook/master/src/.vuepress/public/composition.png" alt="vuejs-course banner"></a> <br> <div class="info"><small>
    Hi! Get $10 off my
    <a href="https://vuejs-course.com/" target="_blank">new</a> <a href="https://vuejs-course.com/" target="_blank">course</a> <a href="https://vuejs-course.com/" target="_blank">on</a> <a href="https://vuejs-course.com/" target="_blank">Vue.js 3</a>,
    <a href="https://vuejs-course.com/" target="_blank">TypeScript and</a>,
    <a href="https://vuejs-course.com/" target="_blank">testing</a>,
    with the discount code VUEJS_COURSE_10_OFF.
    </small></div> <nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Select language" class="dropdown-title"><span class="title">言語</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/vuex-actions.html" class="nav-link">English</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/vuex-actions.html" class="nav-link">v3</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ja/vuex-actions.html" class="nav-link router-link-exact-active router-link-active">日本語</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ru/vuex-actions.html" class="nav-link">Русский (Vue.js 2)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/ru/vuex-actions.html" class="nav-link">Русский (Vue.js 3)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/zh-CN/vuex-actions.html" class="nav-link">简体中文</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ko/vuex-actions.html" class="nav-link">한국어</a></li></ul></div></div> <a href="https://github.com/lmiller1990/vue-testing-handbook" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><a href="/vue-testing-handbook/ja/" class="sidebar-link">ようこそ</a></li><li><a href="/vue-testing-handbook/ja/setting-up-for-tdd.html" class="sidebar-link">テスト駆動開発環境を準備</a></li><li><a href="/vue-testing-handbook/ja/rendering-a-component.html" class="sidebar-link">コンポーネントをレンダー</a></li><li><a href="/vue-testing-handbook/ja/components-with-props.html" class="sidebar-link">プロップスのテスト</a></li><li><a href="/vue-testing-handbook/ja/computed-properties.html" class="sidebar-link">算出プロパティ</a></li><li><a href="/vue-testing-handbook/ja/simulating-user-input.html" class="sidebar-link">ユーザー入力をシミュレーション</a></li><li><a href="/vue-testing-handbook/ja/testing-emitted-events.html" class="sidebar-link">発生したイベントのテスト</a></li><li><a href="/vue-testing-handbook/ja/mocking-global-objects.html" class="sidebar-link">グローバルオブジェクトのモック</a></li><li><a href="/vue-testing-handbook/ja/stubbing-components.html" class="sidebar-link">コンポーネントをスタブする</a></li><li><a href="/vue-testing-handbook/ja/finding-elements-and-components.html" class="sidebar-link">要素とコンポーネントを検索する</a></li><li><a href="/vue-testing-handbook/ja/testing-vuex.html" class="sidebar-link">Vuexのテストの紹介</a></li><li><a href="/vue-testing-handbook/ja/vuex-mutations.html" class="sidebar-link">Vuex - ミューテーション</a></li><li><a href="/vue-testing-handbook/ja/vuex-actions.html" class="active sidebar-link">Vuex - アクション</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ja/vuex-actions.html#アクションを作成する" class="sidebar-link">アクションを作成する</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ja/vuex-actions.html#テストを書く" class="sidebar-link">テストを書く</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ja/vuex-actions.html#api-のエラー時のテストを書く" class="sidebar-link">API のエラー時のテストを書く</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ja/vuex-actions.html#改良" class="sidebar-link">改良</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ja/vuex-actions.html#結論" class="sidebar-link">結論</a></li></ul></li><li><a href="/vue-testing-handbook/ja/vuex-getters.html" class="sidebar-link">Vuex - ゲッター</a></li><li><a href="/vue-testing-handbook/ja/vuex-in-components.html" class="sidebar-link">コンポーネントの中でVuexのテスト</a></li><li><a href="/vue-testing-handbook/ja/vuex-in-components-mutations-and-actions.html" class="sidebar-link">Vuex in components - mutations and actions</a></li><li><a href="/vue-testing-handbook/ja/vue-router.html" class="sidebar-link">Vueルーター</a></li><li><a href="/vue-testing-handbook/ja/jest-mocking-modules.html" class="sidebar-link">Jestでモジュールをモック</a></li><li><a href="/vue-testing-handbook/ja/composition-api.html" class="sidebar-link">Composition API</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>Actions の単体テストは特に面倒なことなく実行できます。これは mutations の単体テストがシンプルに可能であることとよく似ています。mutation のテストについては以前の記事を参照してください。Component から actions を発行する test に関してはこの記事を参照してください。<a href="https://lmiller1990.github.io/vue-testing-handbook/vuex-in-components-mutations-and-actions.html" target="_blank" rel="noopener noreferrer">こちら<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <p>このページで扱っている test は、このリポジトリにあります。<a href="https://github.com/lmiller1990/vue-testing-handbook/blob/master/demo-app/tests/unit/actions.spec.js" target="_blank" rel="noopener noreferrer">リポジトリ<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <h2 id="アクションを作成する"><a href="#アクションを作成する" class="header-anchor">#</a> アクションを作成する</h2> <p>作成する action は一般的な Vuex パターンに従ったものです。</p> <ul><li>API に対して非同期にコールをし、</li> <li>レスポンスデータに対してなんらかの加工をし、(必須ではありませんが)</li> <li>その結果を payload にのせて mutation に対して commit する。</li></ul> <p>つまりこれは認証をおこなう action で、username と password を外部の API に送って、それが正しいものかどうかを判断します。その結果を使って <code>SET_AUTHENTICATED</code> mutation にコミットし、state を変更します。</p> <div class="language-js:title=action extra-class"><pre class="language-text"><code>import axios from &quot;axios&quot;

export default {
  async authenticate({ commit }, { username, password }) {
    const authenticated = await axios.post(&quot;/api/authenticate&quot;, {
      username, password
    })

    commit(&quot;SET_AUTHENTICATED&quot;, authenticated)
  }
}
</code></pre></div><p>この action のテストでは以下の項目を検査する必要があります。</p> <ul><li>API のエンドポイントは正しいか</li> <li>payload は正しいか</li> <li><code>commit</code> の結果引き起こされた <code>mutaiton</code> は正しいものだったか</li></ul> <p>ではまずはテストを書いてから、その失敗メッセージに従って進めていきましょう。</p> <h2 id="テストを書く"><a href="#テストを書く" class="header-anchor">#</a> テストを書く</h2> <div class="language-js:title=action のテスト extra-class"><pre class="language-text"><code>describe(&quot;authenticate&quot;, () =&gt; {
  it(&quot;authenticated a user&quot;, async () =&gt; {
    const commit = jest.fn()
    const username = &quot;alice&quot;
    const password = &quot;password&quot;

    await actions.authenticate({ commit }, { username, password })

    expect(url).toBe(&quot;/api/authenticate&quot;)
    expect(body).toEqual({ username, password })
    expect(commit).toHaveBeenCalledWith(
      &quot;SET_AUTHENTICATED&quot;, true)
  })
})
</code></pre></div><p><code>axios</code> は非同期に処理を行うので、Jest はその処理が終わることを待つ必要があります。そのためには async を宣言し、await で <code>actions.authenticate</code> の呼び出しを待ちます。そうしないとテストは <code>expect</code> の宣言の前に終わってしまうので、このテストは決して色褪せることのない新緑のようなテストということになってしまいます。つまり、決して失敗しないテストになってしまいます。</p> <p>上記テストを実行すると以下のようなテスト失敗のメッセージが表示されます。</p> <div class="language- extra-class"><pre class="language-text"><code> FAIL  tests/unit/actions.spec.js
  ● authenticate › authenticated a user

    SyntaxError: The string did not match the expected pattern.

      at XMLHttpRequest.open (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:482:15)
      at dispatchXhrRequest (node_modules/axios/lib/adapters/xhr.js:45:13)
      at xhrAdapter (node_modules/axios/lib/adapters/xhr.js:12:10)
      at dispatchRequest (node_modules/axios/lib/core/dispatchRequest.js:59:10)
</code></pre></div><p>このエラーは axios の中で起きているエラーです。<code>/api/authenticate</code> に対して axios でリクエストをしていますが、test 環境でこれを実行しているために、このリクエストを受けるエンドポイントがないためにエラーが起きています。加えて <code>url</code> と <code>body</code> も定義されていませんが、これは axios の問題を処理した後で対応することとします。</p> <p>このシリーズ記事では、Jest をテストツールに使用しているので、Jest の mock 機能である jest.mock を使うことで容易にに API の呼び出しをモック化することができます。本当の Axios ではなく、それをモック化したものを使うことで、よりその挙動をコントロールすることができるのです。Jest の提供する ES6 Class Mock が、Axios をモック化するのに最適な機能です。</p> <p>Axios のモックは次のようなコードになります。</p> <div class="language-js:title=Jest の内部で axios を mock 化する extra-class"><pre class="language-text"><code>let url = ''
let body = {}

jest.mock(&quot;axios&quot;, () =&gt; ({
  post: (_url, _body) =&gt; { 
    return new Promise((resolve) =&gt; {
      url = _url
      body = _body
      resolve(true)
    })
  }
}))
</code></pre></div><p>この axios の mock は、url と body を変数に記録します。その目的は、「エンドポイント」と受け取った「payload」が正しいことをテストで宣言するためです。</p> <p>(訳注: この axios を mock した関数は、実際に axios が実行される場合に代わりに実行される。そしてここで定義した mock は、<code>.post</code> というメソッドを持ち、このメソッドは <code>_url</code> と <code>_body</code> を受け取る。つまりこの mock は、元の axios が <code>axios.post(someUrl, { someBody })</code> という形で実行される際に、割り込んで <code>post: (_url, _body) =&gt; {}</code> を実行するのだ。結果として、グローバル変数に置かれた <code>url</code> と　<code>body</code> に値が代入される。この値を assertion で使用するというわけだ。)</p> <p>本当のエンドポイントを実行したいわけではないので、このモックは Primise を即時解決させて、API が成功した状態を擬似的に再現しています。</p> <p><code>yarn unit:pass</code> を実行してみると、やっとテストが通りますね！</p> <h2 id="api-のエラー時のテストを書く"><a href="#api-のエラー時のテストを書く" class="header-anchor">#</a> API のエラー時のテストを書く</h2> <p>API の呼び出しが「成功」した場合のみをテストしてきました。しかし、考えうる結果すべてをテストすることが非常に重要です。ですから、Error が発生した場合のテストを書いていくことにしましょう。今回もまずはテストを書いて、それに従って API を実装していくことしましょう。</p> <p>テストは次のように書くことができるでしょう。</p> <div class="language-js:title=Jest による test extra-class"><pre class="language-text"><code>it(&quot;catches an error&quot;, async () =&gt; {
  mockError = true

  await expect(actions.authenticate({ commit: jest.fn() }, {}))
    .rejects.toThrow(&quot;エラーが起きました.&quot;)
})
</code></pre></div><p>axios mock に強制的に <code>thow an error</code> させる必要があります。そのために <code>mockError</code> 変数を用意します。次のように書き換えましょう。</p> <div class="language-js:title=Jest による test extra-class"><pre class="language-text"><code>let url = ''
let body = {}
let mockError = false

jest.mock(&quot;axios&quot;, () =&gt; ({
  post: (_url, _body) =&gt; { 
    return new Promise((resolve) =&gt; {
      if (mockError) 
        throw Error()

      url = _url
      body = _body
      resolve(true)
    })
  }
}))
</code></pre></div><p>Jest の ES6 class mock は、名前が <code>mock</code> から始まる変数に限っては、scope の外側の変数でも参照することができます。ですので、mockError という変数を単純に <code>true</code> にセットすることで axios mock にエラーを起こしてもらうことにしましょう。</p> <p>すると次のようなエラーがでるはずです。</p> <div class="language- extra-class"><pre class="language-text"><code>FAIL  tests/unit/actions.spec.js
● authenticate › catchs an error

  expect(function).toThrow(string)

  Expected the function to throw an error matching:
    &quot;エラーが起きました&quot;
  Instead, it threw:
    Mock error
</code></pre></div><p>エラーはうまく起こせましたが、期待した挙動にはなっていませんね。authenticate メソッドを修正し、期待した error が throw されるように修正しましょう。</p> <div class="language-js:title=action を修正する extra-class"><pre class="language-text"><code>export default {
  async authenticate({ commit }, { username, password }) {
    try {
      const authenticated = await axios.post(&quot;/api/authenticate&quot;, {
        username, password
      })

      commit(&quot;SET_AUTHENTICATED&quot;, authenticated)
    } catch (e) {
      throw Error(&quot;エラーが起きました。&quot;)
    }
  }
}
</code></pre></div><p>これでテストが通るようになりましたね。</p> <h2 id="改良"><a href="#改良" class="header-anchor">#</a> 改良</h2> <p>Action を単体テストすることができました。ただし、このテストは少なくとも一箇所、大幅に改善できる余地が残されています。それは axios の mock を manual mock として実装することです。<code>__mocks__</code> ディレクトリを <code>node_modules</code> ディレクトリと同階層に作成し、<code>__mocks__</code> に mock module を配置します。こうすることでこの mock を全てのテストで使いまわすことができます。Jest は <code>__mocks__</code> 配下にある mock を自動的に使ってくれます。これに関する例示は、Jest 公式サイトにもそれからインターネットにもたくさんあります。このテストの manual mock を使った改善については、皆さんへの宿題として残しておくことにしますね。</p> <h2 id="結論"><a href="#結論" class="header-anchor">#</a> 結論</h2> <p>この記事では以下のことを扱ってきました。</p> <ul><li>Jest の ES6 class mock の使用</li> <li>action の 成功/失敗時 のテスト</li></ul> <p>この記事のテストの完成形は<a href="https://github.com/lmiller1990/vue-testing-handbook/blob/master/demo-app/tests/unit/actions.spec.js" target="_blank" rel="noopener noreferrer">こちら<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>にあります。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/lmiller1990/vue-testing-handbook/edit/master/ja/vuex-actions.md" target="_blank" rel="noopener noreferrer">GitHub上で編集</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <div class="last-updated"><span class="prefix">更新:</span> <span class="time">2018/12/10 22:04:24</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/vue-testing-handbook/ja/vuex-mutations.html" class="prev">Vuex - ミューテーション</a></span> <span class="next"><a href="/vue-testing-handbook/ja/vuex-getters.html">Vuex - ゲッター</a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/vue-testing-handbook/assets/js/app.14051834.js" defer></script><script src="/vue-testing-handbook/assets/js/3.119a321e.js" defer></script><script src="/vue-testing-handbook/assets/js/2.94957ecd.js" defer></script><script src="/vue-testing-handbook/assets/js/25.48371e8a.js" defer></script>
  </body>
</html>
